const buildBizContent = Symbol('buildBizContent') ;
const signWithPrivateKey = Symbol('signWithPrivateKey') ;
const buildSign = Symbol('buildSign') ;
const verifySignWithAlipayKey = Symbol('verifySignWithAlipayKey');
const fs = require('fs') ;
const crypto = require('crypto') ;
const path = require('path') ;
const moment = require('moment') ;
/***
 * Alipay类
 */
class Alipay {
    /***
     * 构造器
     * @param config {object}  基本配置参数
     * @returns undefined
     */
  constructor(config){
    this.setting = config ;
  }
    /***
     *订单基本信息  //签名方法
     * @param  subject     商品的标题/交易标题/订单标题/订单关键字等。
     * @param  outTradeNo  商户网站唯一订单号
     * @param  totalAmount 订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
     * @returns {string}   json字符串
     */

  buildParams(subject , outTradeNo , totalAmount){
    let params = new Map() ;
    params.set('app_id',"2016091000481268")
          //alipay.trade.precreate
        //alipay.trade.wap.pay
          .set('method','alipay.trade.wap.pay')
          .set('charset','utf-8')
          .set('sign_type','RSA2')
          .set('timestamp',moment().format('YYYY-MM-DD HH:mm:ss'))
          .set('version','1.0')
          .set('notify_url',"http://129.204.112.231:8000/paySuccess")
          // .set('notify_url',this.setting.APP_REDIRECT_URL)
          .set('return_url',"http://localhost:8080/#/myOrder") //支付完成 跳转回我的订单页【支付宝带参数】
          // .set('return_url',this.setting.APP_RETURN_URL)
          .set('biz_content',this[buildBizContent](subject , outTradeNo , totalAmount ))
          .set('sign',this[buildSign](params)) ;
    return   [ ...params ].map(([key ,item])=> `${key}=${encodeURIComponent(item)}`).join("&") ;
  }
    /***
     *订单基本信息
     * @param  subject     商品的标题/交易标题/订单标题/订单关键字等。
     * @param  outTradeNo  商户网站唯一订单号
     * @param  totalAmount 订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
     * @returns {string}   json字符串
     * @private
     */
    [buildBizContent](subject , outTradeNo , totalAmount ){
      let bizContent = {
          subject:subject,
          out_trade_no:outTradeNo,
          total_amount:totalAmount,
          product_code:'QUICK_MSECURITY_PAY'
      };
      return JSON.stringify(bizContent) ;
  }
    /***
     *
     * @param params {map} 参数集合
     * @returns {*} 用私钥签名后的参数[除sign]字符串
     */
    [buildSign]( params ){
        let signType = params.get( 'sign_type' ) ;
        let paramsMap = [ ...params ].filter(([key ,item])=> key !== 'sign'&&item) ;
        let sorted_parmas = paramsMap.sort() ;
        let paramsString = sorted_parmas.map(([key ,item])=> `${key}=${item}`).join('&');
        // console.log(paramsString);
        return this[signWithPrivateKey]( signType ,paramsString )
    }
    /***
     *
     * @param signType      签名类型[RSA/RSA2]
     * @param paramsString  参数排序后的&字符串
     */
    [signWithPrivateKey]( signType ,paramsString ){
        const APP_PRIVATE_KEY = fs.readFileSync( path.join(__dirname,'pem','rsa_private_key.pem'),'utf8') ;
        const SIGN_WAYS = {
            RSA2:()=>crypto.createSign('RSA-SHA256'),
            RSA:()=>crypto.createSign('RSA-SHA1')
        } ;
        let sign = SIGN_WAYS[signType]?SIGN_WAYS[signType]():throwError('correct signType needed');
        sign.update(paramsString);
        return sign.sign(APP_PRIVATE_KEY , 'base64') ;
    }
    //验签方法
    verifySign(aliReturnParams){
        let {sign ,sign_type} = aliReturnParams ;
        let paramsMap = new Map() ;
        for(let key in aliReturnParams) paramsMap.set(key , aliReturnParams[key]) ;
        let sortedParams = [...paramsMap].filter(([key,item])=>key!=='sign'&&key!=='sign_type'&&item).sort();
        let paramsStirng = sortedParams.map(([key,item])=>`${key}=${item}`).join("&") ;
        return this[verifySignWithAlipayKey](sign ,sign_type , paramsStirng )
    }
    [verifySignWithAlipayKey]( sign ,signType ,paramsString){
        const ALI_PUBLIC_KEY = fs.readFileSync( './pem/ali_public_key.pem' ,'utf8') ;
        const VERIFY_WAYS = {
            RSA2:()=>crypto.createVerify('RSA-SHA256'),
            RSA:()=>crypto.createVerify('RSA-SHA1')
        } ;
        let verify = VERIFY_WAYS[signType]?VERIFY_WAYS[signType]():throwError('correct verify needed') ;
        verify.update(paramsString);
        return verify.verify( ALI_PUBLIC_KEY ,sign ,'base64' )
    }
}
// let config = {
//     APP_ID:"2016091000481268",
//     APP_REDIRECT_URL:"http://127.0.0.1:3030",
//     APP_PRIVATE_KEY_PATH:path.join(__dirname,'pem','rsa_private_key.pem'),
//     APP_PUBLIC_KEY_PATH:"",
//     ALI_PUBLIC_KEY_PATH:"",
// };

module.exports = Alipay ;





